#import "DetailViewController+AddListItemSheet.h"
#import "RNConstants.h"
#import "RNList.h"
#import "RNListItem.h"
#import "RNItem.h"
#import "RNHistoryItem.h"
#import "RNFilteringArrayController.h"
#import "MainWindowController.h"
#import "RNNewItemSheetController.h"
#import "RNSegmentedControl.h"
#import "NSManagedObjectContext+SRAdditions.h"

@interface SearchCountTransformer : NSValueTransformer {} @end
@implementation SearchCountTransformer

+(Class)transformedValueClass {
    return [NSString class];
}
+(BOOL)allowsReverseTransformation {
    return NO;
}
-(id)transformedValue:(id)value {
    NSAssert([value isKindOfClass:[NSNumber class]], @"SearchCountTransformer: transforming value that isn't of class NSNumber");
    if ([value integerValue] == 0)
        return @"No search results";
    return [NSString stringWithFormat:@"%@ %@ found", value, [value integerValue] == 1 ? @"item" : @"items"];
}
@end


@implementation DetailViewController (DetailViewControllerAddListItemSheetMethods)

-(NSArray *)addListItemControllerDescriptors {
    if (!addListItemControllerDescriptors_) {
        NSSortDescriptor *confidenceDescriptor = [[NSSortDescriptor alloc] initWithKey:@"confidence" ascending:NO];
        NSSortDescriptor *favoriteDescriptor = [[NSSortDescriptor alloc] initWithKey:@"favorite" ascending:YES];
        NSSortDescriptor *titleDescriptor = [[NSSortDescriptor alloc] initWithKey:@"title" ascending:YES];
        NSSortDescriptor *lastUsedDescriptor = [[NSSortDescriptor alloc] initWithKey:@"dateLastUsed" ascending:NO];
        addListItemControllerDescriptors_ = [NSArray arrayWithObjects:confidenceDescriptor, favoriteDescriptor, lastUsedDescriptor, titleDescriptor, nil];
    }
    return addListItemControllerDescriptors_;
}

-(NSWindow *)addListItemSheet {
    if (!addListItemSheet_) {
        NSAssert([NSBundle loadNibNamed:@"AddListItemSheet" owner:self], @"DetailViewController:addListItemSheet: error loading nib");
        [[[self addListItemTitleField] cell] setBackgroundStyle:NSBackgroundStyleRaised];
        [addListItemSheet_ setNextResponder:self];
        [NSValueTransformer setValueTransformer:[[SearchCountTransformer alloc] init] forName:@"ZeroIsNullTransformer"];
        [[self addAndRepeatButton] setKeyEquivalent:@"r" forSegment:0];
        [[self addAndRepeatButton] setKeyEquivalentModifierMask:(NSCommandKeyMask | NSAlternateKeyMask) forSegment:0];
        [[self searchResultsTable] setDoubleAction:@selector(addSelectedItem:)];
    }
    return addListItemSheet_;
}

-(void)addListItemSheetDidEnd:(NSWindow *)sheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo {
    [sheet orderOut:self];
    [[self addListItemSearchField] setStringValue:@""];
    [[self addAndRepeatButton] setSelected:NO forSegment:0];
    [[self filteredItemsArrayController] filterWithString:@""];
}

-(IBAction)displayAddListItemSheet:(id)sender {
    NSWindow *sheet = [self addListItemSheet];
    [NSApp beginSheet:sheet modalForWindow:[NSApp mainWindow] modalDelegate:self didEndSelector:@selector(addListItemSheetDidEnd:returnCode:contextInfo:) contextInfo:nil];
}

-(IBAction)cancelAddListItemSheet:(id)sender {
    [NSApp endSheet:[self addListItemSheet]];
}

-(IBAction)searchStringChanged:(id)sender {
    NSString *searchString = [[self addListItemSearchField] stringValue];
    [[self filteredItemsArrayController] filterWithString:searchString];
    if ([[[self filteredItemsArrayController] selectedObjects] count] == 0 && [[[self filteredItemsArrayController] arrangedObjects] count] > 0)
        [[self filteredItemsArrayController] setSelectionIndex:0];
}

-(IBAction)addSelectedItem:(id)sender {
    NSAssert([[self rootObject] isKindOfClass:[RNList class]], @"Adding list item to root object that isn't of class List");

    // Repeat button clicked - nothing to do
    if ([[self addAndRepeatButton] selectedSegment] == 0) 
        return;
    // Otherwise 'Add Item' segment was clicked - restore it to unselected state
    [[self addAndRepeatButton] setSelected:NO forSegment:1];
    
    NSInteger selectedRow = [[self searchResultsTable] selectedRow];
    if (selectedRow == -1) {
        NSBeep();
        return;
    }
        
    RNItem *selectedItem = [[[self filteredItemsArrayController] arrangedObjects] objectAtIndex:selectedRow];
    if (![[self addAndRepeatButton] isSelectedForSegment:0])
        [NSApp endSheet:[self addListItemSheet]];
    else {
        [[self filteredItemsArrayController] filterWithString:@""];
        [[self addListItemSearchField] setStringValue:@""];
    }

    RNListItem *newListItem = [NSEntityDescription insertNewObjectForEntityForName:RNEntityNameListItem inManagedObjectContext:[self managedObjectContext]];
    [newListItem setNotes:[self historicNotesForItem:selectedItem]];
    [newListItem setTags:[self historicTagsForItem:selectedItem]];
    [newListItem setCount:[self historicCountForItem:selectedItem]];
    [newListItem setItem:selectedItem];
    [newListItem setCategory:[selectedItem category]];
    [newListItem addAisles:[selectedItem aisles]];
    [newListItem setList:[self rootObject]];
}

-(NSString *)historicNotesForItem:(RNItem *)item {
    NSArray *itemHistory = [[self managedObjectContext] fetchObjectsForEntityName:RNEntityNameHistoryItem withPredicate:@"item == %@", item];
    itemHistory = [itemHistory sortedArrayUsingDescriptors:[NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:@"loggedDate" ascending:NO]]];
    itemHistory = [itemHistory subarrayWithRange:NSMakeRange(0, fmin(3, [itemHistory count]))];
    NSMutableDictionary *notesDictionary = [NSMutableDictionary dictionary];
    for (RNHistoryItem *historyItem in itemHistory) {
        NSString *notes = [historyItem notes];
        if (!notes)
            continue;
        NSNumber *currentCount = [notesDictionary valueForKey:notes];
        NSUInteger count = currentCount ? [currentCount unsignedIntegerValue] + 1 : 1;
        [notesDictionary setValue:[NSNumber numberWithUnsignedInteger:count] forKey:notes];
    }
    NSArray *mostCommonKeys = [notesDictionary keysSortedByValueUsingSelector:@selector(compare:)];
    NSString *mostCommonNote = [mostCommonKeys lastObject];
    NSUInteger totalCount = [itemHistory count];
    NSUInteger mostCommonCount = [[notesDictionary valueForKey:mostCommonNote] unsignedIntegerValue];
    if (totalCount - mostCommonCount <= 1)
        return mostCommonNote;
    return nil;
}

-(NSArray *)historicTagsForItem:(RNItem *)item {
    NSArray *itemHistory = [[self managedObjectContext] fetchObjectsForEntityName:RNEntityNameHistoryItem withPredicate:@"item == %@", item];
    itemHistory = [itemHistory sortedArrayUsingDescriptors:[NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:@"loggedDate" ascending:NO]]];
    itemHistory = [itemHistory subarrayWithRange:NSMakeRange(0, fmin(3, [itemHistory count]))];
    NSMutableDictionary *tagsDictionary = [NSMutableDictionary dictionary];
    for (RNHistoryItem *historyItem in itemHistory) {
        NSArray *tags = [historyItem tags];
        if (!tags)
            continue;
        for (NSString *tag in tags) {
            NSNumber *currentCount = [tagsDictionary valueForKey:tag];
            NSUInteger count = currentCount ? [currentCount unsignedIntegerValue] + 1 : 1;
            [tagsDictionary setValue:[NSNumber numberWithUnsignedInteger:count] forKey:tag];
        }
    }
    NSUInteger totalCount = [itemHistory count];
    NSMutableArray *commonTags = [NSMutableArray arrayWithCapacity:totalCount];
    for (NSString *tag in tagsDictionary) {
        NSUInteger tagCount = [[tagsDictionary valueForKey:tag] unsignedIntegerValue];
        if (totalCount - tagCount <= 1)
            [commonTags addObject:tag];
    }
    return [commonTags count] == 0 ? nil : commonTags;
}

-(NSNumber *)historicCountForItem:(RNItem *)item {
    NSArray *itemHistory = [[self managedObjectContext] fetchObjectsForEntityName:RNEntityNameHistoryItem withPredicate:@"item == %@", item];
    itemHistory = [itemHistory sortedArrayUsingDescriptors:[NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:@"loggedDate" ascending:NO]]];
    itemHistory = [itemHistory subarrayWithRange:NSMakeRange(0, fmin(3, [itemHistory count]))];
    NSMutableDictionary *countDictionary = [NSMutableDictionary dictionary];
    for (RNHistoryItem *historyItem in itemHistory) {
        NSNumber *count = [historyItem count];
        if (!count)
            continue;
        NSNumber *currentNumber = [countDictionary objectForKey:count];
        NSUInteger number = currentNumber ? [currentNumber unsignedIntegerValue] + 1 : 1;
        [countDictionary setObject:[NSNumber numberWithUnsignedInteger:number] forKey:count];
    }
    NSArray *mostCommonKeys = [countDictionary keysSortedByValueUsingSelector:@selector(compare:)];
    NSNumber *mostCommonCount = [mostCommonKeys lastObject];
    if (!mostCommonCount)
        return [NSNumber numberWithInteger:1];
    NSUInteger totalCount = [itemHistory count];
    NSUInteger mostCommonNumber = [[countDictionary objectForKey:mostCommonCount] unsignedIntegerValue];
    if (totalCount - mostCommonNumber <= 1)
        return mostCommonCount;
    return [NSNumber numberWithInteger:1];
}

-(IBAction)createNewItem:(id)sender {
    NSString *searchString = [[[self addListItemSearchField] stringValue] capitalizedString];
    [NSApp endSheet:[self addListItemSheet]];
    MainWindowController *windowController = [[NSApp mainWindow] windowController];
    NSAssert([windowController isKindOfClass:[MainWindowController class]], @"RNAddItemViewController:executeMenuExtraAtRow: windowController not of class MainWindowController");
    RNNewItemSheetController *newItemSheetController = [windowController newItemSheetController];
    [newItemSheetController createItemWithString:searchString addToList:[self rootObject]];
}

-(BOOL)control:(NSControl *)control textView:(NSTextView *)textView doCommandBySelector:(SEL)command {
    NSInteger selectedRow = -1;
    if (command == @selector(moveUp:)) {
        selectedRow = [[self searchResultsTable] selectedRow];
        if (selectedRow > 0)
            [[self searchResultsTable] selectRowIndexes:[NSIndexSet indexSetWithIndex:--selectedRow] byExtendingSelection:NO];
        [[self searchResultsTable] scrollRowToVisible:selectedRow];
        return YES;
    }
    else if (command == @selector(moveDown:)) {
        selectedRow = [[self searchResultsTable] selectedRow];
        if (selectedRow < ([[self searchResultsTable] numberOfRows] - 1))
            [[self searchResultsTable] selectRowIndexes:[NSIndexSet indexSetWithIndex:++selectedRow] byExtendingSelection:NO];
        [[self searchResultsTable] scrollRowToVisible:selectedRow];
        return YES;
    }
    else if (command == @selector(insertNewline:)) {
        [[self addAndRepeatButton] performClickOnSegment:1];
//        [self addSelectedItem:nil];
        return YES;
    }
    else if (command == @selector(cancelOperation:)) {
        [[self cancelAddListItemButton] performClick:self];
        return YES;
    }
    return NO;
}    

@end
